﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	RouterFactory.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;

namespace Smart.Common.Router
{
	/// <summary>
	/// Router factory
	/// </summary>
	public class RouterFactory : IRouterFactory
	{
		public SPServicesInstance Services { get; set; }

		public RouterFactory(SPServicesInstance services)
		{
			Services = services;
		}

		/// <summary>
		/// Register router service
		/// </summary>
		public static void Register<TRouterServiceType>(string serviceName)
			where TRouterServiceType : class, IRouterService, new()
		{
			SPServices.ServiceLocator.Register<IRouterService, TRouterServiceType>(serviceName);
		}

		/// <summary>
		/// Unregister router service
		/// </summary>
		public static void Unregister(string serviceName)
		{
			SPServices.ServiceLocator.Unregister<IRouterService>(serviceName);
		}

		/// <summary>
		/// Returns router service
		/// </summary>
		public IRouterService Get<TRouterServiceType>(string serviceName)
			where TRouterServiceType : class, IRouterService
		{
			return Services.ServiceLocator.GetInstance<TRouterServiceType>(serviceName);
		}

		/// <summary>
		/// Get router service by router type name
		/// </summary>
		public virtual IRouterService GetService(string serviceName)
		{
			var service = Get<IRouterService>(serviceName);

			if (service == null)
				throw new ArgumentOutOfRangeException("serviceName: " + serviceName);

			service.InitContext(serviceName);

			service.InitService();

			return service;
		}

		/// <summary>
		/// Ensure that uri corresponds to the real path
		/// </summary>		
		/// <returns>True if uri exists, false otherwise</returns>
		public virtual bool EnsureUriExists(string serviceName, string uri)
		{
			var service = GetService(serviceName);

			return service.EnsureUriExists(uri);
		}

		///// <summary>
		///// Get formatted uri and template type by name. Ensure that uri corresponds to the real path.
		///// </summary>
		//public virtual string EnsureGetUri(string serviceName, string name, out string type, params object[] values)
		//{
		//	var service = GetService(serviceName);
		//
		//	return service.GetUri(name, out type, values);
		//}
		//
		///// <summary>
		///// Get formatted uri. Ensure that uri corresponds to the real path. 
		///// </summary>
		//public virtual string EnsureGetUri(string serviceName, string name, params object[] values)
		//{
		//	var service = GetService(serviceName);
		//
		//	return service.GetUri(name, values);
		//}

		/// <summary>
		/// Get formatted uri and template type by name
		/// </summary>
		public virtual string GetUri(string serviceName, string name, out string type, params object[] values)
		{
			var service = GetService(serviceName);

			return service.GetUri(name, out type, values);
		}

		/// <summary>
		/// Get formatted uri
		/// </summary>
		public virtual string GetUri(string serviceName, string name, params object[] values)
		{
			var service = GetService(serviceName);

			return service.GetUri(name, values);
		}

		/// <summary>
		/// Get object specified by name and values
		/// </summary>
		public virtual object Get(string serviceName, string name, params object[] values)
		{
			var service = GetService(serviceName);

			return service.Get(name, values);
		}

		/// <summary>
		/// Get templated object specified by name and values
		/// </summary>
		public virtual TObjectType Get<TObjectType>(string serviceName, string name, params object[] values)
			where TObjectType : class
		{
			return Get(serviceName, name, values) as TObjectType;
		}

		/// <summary>
		/// Add router template to the source if not exists
		/// </summary>
		/// <returns>True if router template doesn't exist and it was added. Otherwise false.</returns>
		public virtual bool AddOrUpdateTemplate(string serviceName, RouterTemplate template)
		{
			var service = GetService(serviceName);

			return service.AddOrUpdateTemplate(template);
		}
	}
}